/*
 * Copyright 2009-2010 Nanjing RedOrange ltd (http://www.red-orange.cn)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package redora.util;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import redora.service.BusinessRuleViolation;
import redora.service.BusinessRuleViolation.StandardRule;

import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

/**
 * For test cases you might want to use one of these static functions. The assertRedoraPersist function
 * will check violated business rules and fail the test if appropriate.
 *
 * @author Nanjin RedOrange (www.red-orange.cn)
 */
public class JUnitUtil {

    /**
     * Check the returned business rules. If one or more BR's are violated, the
     * test case will fail.
     *
     * @param ret (Mandatory) The return of the persist action
     * @param ruleId
     *            (Optional) set the BR here that you expect to violate, on this BR
     *            the test will not fail.
     * @param message (Optional) a custom message you wish to display
     */
    public static void assertRedoraPersist(@Nullable String message
            , @NotNull Set<BusinessRuleViolation> ret, @Nullable Integer ruleId) {
        for (BusinessRuleViolation violation : ret) {
            StringBuilder mes = new StringBuilder();
            if (message != null) {
                mes.append('[').append(mes).append("] ");
            }
            mes.append("Unexpected business rule violation: ");
            mes.append(violation.getBusinessRuleId()).append(" is violated for field ");
            mes.append(violation.getField()).append(" on ");
            mes.append( violation.getPersistable().getClass().getName());
            if (ruleId != null) {
                assertEquals(mes.toString(), violation.getBusinessRuleId(), ruleId);
            } else {
                fail(mes.toString());
            }
        }
        if (ruleId != null && ret.isEmpty()) {
            fail("[" + message + "] I expected the violation of rule: " + ruleId
                    + ", but this rule did not fire");
        }
    }

    /**
     * Convenience wrapper on checkPersistResult using the default message
     * @param ret (Mandatory) The return of the persist action
     * @param rule
     *            (Optional) set the BR here that you expect to violate, on this BR
     *            the test will not fail.
     */
    public static void assertRedoraPersist(@NotNull Set<BusinessRuleViolation> ret,
            @Nullable StandardRule rule) {
        assertRedoraPersist(null, ret, rule == null ? null : rule.ruleId);
    }

    /**
     * Convenience wrapper on checkPersistResult using the default message
     * @param ret (Mandatory) The return of the persist action
     * @param rule
     *            (Optional) set the BR here that you expect to violate, on this BR
     *            the test will not fail.
     * @param message (Optional) a custom message you wish to display
     */
    public static void assertRedoraPersist(@Nullable String message, @NotNull Set<BusinessRuleViolation> ret,
            @Nullable StandardRule rule) {
        assertRedoraPersist(message, ret, rule == null ? null : rule.ruleId);
    }


    /**
     * Convenience wrapper on checkPersistResult using the default message and does
     * not allow any business rules to fail
     * @param ret (Mandatory) The return of the persist action
     */
    public static void assertRedoraPersist(@NotNull Set<BusinessRuleViolation> ret) {
        assertRedoraPersist(null, ret, (Integer) null);
    }
}
